﻿using System.Web.Routing;
using TeamsPortal.Configuration.Routing;
using TeamsPortal.Web.Extensions;
using NUnit.Framework;
using TeamsPortal.Web.UI;
using TeamsPortal.Tests.Fakes;
using MvcRouteUnitTester;
using TeamsPortal.Web.Output2;
using System.Web.Mvc;
using System.Web;
using Moq;

namespace TeamsPortal.Tests.Routing
{
    [TestFixture]
	public class RoutingTest
	{
        private RouteCollection _routes;

        [TestFixtureSetUp]
        public void Init()
        {
            _routes = new RouteCollection();
            RouteMappingConfiguration routesConfig = RouteMappingConfiguration.Current;

            RoutingHelper.RegisterRoutes(_routes, routesConfig);
        }

        [Test]
        public void ContentRouting()
        {
             //<add url="p/{name}" controller="PageContents" action="Detail">
            RoutingAssert.IsRouteOf(_routes, "p/PageName", new
            {
                controller = "PageContents",
                action = "Detail",
                name = "PageName"
            });
        //<add url="p/{name}/edit" controller="PageContents" action="Edit">
            RoutingAssert.IsRouteOf(_routes, "p/PageName/edit", new
            {
                controller = "PageContents",
                action = "Edit",
                name = "PageName"
            });
      //<add url="p/{name}/delete" controller="PageContents" action="Delete">
            RoutingAssert.IsRouteOf(_routes, "p/PageName/delete", new
            {
                controller = "PageContents",
                action = "Delete",
                name = "PageName"
            });
        }

        [Test]
        public void Topics()
        {
            //<add url="forums/{forum}/{name}-{id}/{page}" controller="Topics" action="Detail">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/TopicName-10/12", new
            {
                controller = "Topics",
                action = "Detail",
                id = 10,
                page = 12,
                forum = "ForumName",
                name = "TopicName"
            });
            //<add url="forums/{forum}/{name}-{id}/page-more" controller="Topics" action="PageMore">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/TopicName-11/page-more", new
            {
                controller = "Topics",
                action = "PageMore",
                id = 11,
                forum = "ForumName",
                name = "TopicName"
            });
            //<add url="forums/{forum}/{name}-{id}/page-until" controller="Topics" action="PageUntil">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/TopicName-11/page-until", new
            {
                controller = "Topics",
                action = "PageUntil",
                id = 11,
                forum = "ForumName",
                name = "TopicName"
            });
            //<add url="forums/{forum}/create-thread" controller="Topics" action="Add">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/create-thread", new
            {
                controller = "Topics",
                action = "Add",
                forum = "ForumName"
            });
            //<add url="forums/{forumName}/{name}-{id}/move" controller="Topics" action="Move">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/TopicName-11/move", new
            {
                controller = "Topics",
                action = "Move",
                id = 11,
                forumName = "ForumName",
                name = "TopicName"
            });
            //<add url="forums/{forum}/{name}-{id}/close" controller="Topics" action="CloseReplies">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/TopicName-11/close", new
            {
                controller = "Topics",
                action = "CloseReplies",
                id = 11,
                forum = "ForumName",
                name = "TopicName"
            });
            //<add url="forums/{forum}/{name}-{id}/delete" controller="Topics" action="Delete">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/TopicName-11/delete", new
            {
                controller = "Topics",
                action = "Delete",
                id = 11,
                forum = "ForumName",
                name = "TopicName"
            });
            //<add url="forums/{forum}/{name}-{id}/open" controller="Topics" action="OpenReplies">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/TopicName-11/open", new
            {
                controller = "Topics",
                action = "OpenReplies",
                id = 11,
                forum = "ForumName",
                name = "TopicName"
            });
            // <add url="forums/{forum}/{name}-{id}/rss" controller="Topics" action="LatestMessages">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/TopicName-11/rss", new
            {
                controller = "Topics",
                action = "LatestMessages",
                id = 11,
                forum = "ForumName",
                name = "TopicName"
            });
            //<add url="forums/{forum}/{name}-{id}/edit" controller="Topics" action="Edit">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/TopicName-11/edit", new
            {
                controller = "Topics",
                action = "Edit",
                id = 11,
                forum = "ForumName",
                name = "TopicName"
            });
            //<add url="forums/{id}" controller="Topics" action="ShortUrl">
            RoutingAssert.IsRouteOf(_routes, "forums/11", new
            {
                controller = "Topics",
                id = 11
            });
        }

        [Test]
        public void Home_New()
        {
            RoutingAssert.IsRouteOf(_routes, "/", new
            {
                controller = "Home",
                action = "Index"
            });
        }

        [Test]
        public void Forums()
        {
        //<add url="forums/rss" controller="Forums" action="LatestAllTopics" />
            RoutingAssert.IsRouteOf(_routes, "forums/rss", new
            {
                controller = "Forums",
                action = "LatestAllTopics"
            });
      //<add url="forums/{forum}/unanswered" controller="Forums" action="ListUnansweredTopics">
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/unanswered", new
            {
                controller = "Forums",
                action = "ListUnansweredTopics",
                forum = "ForumName"
            });
            /*<add url="forums/{forum}/latest/{page}" controller="Forums" action="LatestTopics">
        <defaults>
          <add key="page" value="0" />
          <add key="format" value="Html" />
        </defaults>
      </add>*/
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/latest/8", new
            {
                controller = "Forums",
                action = "LatestTopics",
                forum = "ForumName",
                page = 8
            });
            //RoutingAssert.IsRouteOf(routes, "forums/ForumName/latest", new
            //{
            //    controller = "Forums",
            //    action = "LatestTopics",
            //    forum = "ForumName",
            //    page = 0,
            //    format = ResultFormat.Html
            //});
            /*<add url="forums/{forum}/most-viewed/{page}" controller="Forums" action="MostViewedTopics">
        <defaults>
          <add key="page" value="0" />
        </defaults>
      </add>*/
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/most-viewed/8", new
            {
                controller = "Forums",
                action = "MostViewedTopics",
                forum = "ForumName",
                page = 8
            });
            /*<add url="forums/{forum}/rss" controller="Forums" action="LatestTopics">
        <constraints>
          <add key="forum" value="[\w\-%]+" />
        </constraints>
        <defaults>
          <add key="page" value="0" />
          <add key="format" value="Rss" />
        </defaults>
      </add>*/
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/rss", new
            {
                controller = "Forums",
                action = "LatestTopics",
                forum = "ForumName"
            });
            /*<add url="forums/{forum}/tags/{tag}/{page}" controller="Forums" action="TagDetail">
        <defaults>
          <add key="page" value="0" />
        </defaults>
      </add>*/
            RoutingAssert.IsRouteOf(_routes, "forums/ForumName/tags/tag1/8", new
            {
                controller = "Forums",
                action = "TagDetail",
                forum = "ForumName",
                page = 8,
                tag = "tag1"
            });
        }

       [Test]
		public void Routing_CheckNonAscii_Test()
		{
			//This test is to list assertions on the relation of alphabets and ascii table

			var value = "";
			value = "asdfghjkl"; //English alphabet
			Assert.IsTrue(value.ContainsAsciiChars());

			value = "voçe abusou";
			//Portuguese
			Assert.IsTrue(value.ContainsAsciiChars());

			value = "เที่ยวไทย";
			//Thai
			Assert.IsFalse(value.ContainsAsciiChars());

			value = "안넹";
			//Korean
			Assert.IsFalse(value.ContainsAsciiChars());
		}

        //[Test]
        //public void Routing_Segment_Tests()
        //{
        //    Assert.AreEqual("yeah", "YEAH!!!!!".ToUrlSegment());
        //    Assert.AreEqual("oh-yeah", "OH YEAH".ToUrlSegment());
        //}

        [Test]
        public void AdminArea()
        {
            //<add url="admin/" controller="Admin" action="Dashboard" />
            RoutingAssert.IsRouteOf(_routes, "admin/", new
            {
                controller = "Admin",
                action = "Dashboard"
            });
            //<add url="admin/templates/add" controller="Templates" action="Add" />
            RoutingAssert.IsRouteOf(_routes, "/admin/templates/add", new
            {
                controller = "Templates",
                action = "Add"
            });
            //<add url="admin/templates/set" controller="Templates" action="SetCurrent" />
            RoutingAssert.IsRouteOf(_routes, "admin/templates/set", new
            {
                controller = "Templates",
                action = "SetCurrent"
            });
            //<add url="admin/templates/delete" controller="Templates" action="Delete" />
            RoutingAssert.IsRouteOf(_routes, "admin/templates/delete", new
            {
                controller = "Templates",
                action = "Delete"
            });
            //<add url="admin/templates/export" controller="Templates" action="Export" />
            RoutingAssert.IsRouteOf(_routes, "admin/templates/export", new
            {
                controller = "Templates",
                action = "Export"
            });
            //<add url="admin/templates/preview" controller="Templates" action="Preview" />
            RoutingAssert.IsRouteOf(_routes, "admin/templates/preview", new
            {
                controller = "Templates",
                action = "Preview"
            });
            //<add url="admin/templates/add-defaults" controller="Templates" action="AddDefaultTemplates" />
            RoutingAssert.IsRouteOf(_routes, "admin/templates/add-defaults", new
            {
                controller = "Templates",
                action = "AddDefaultTemplates"
            });
            //<add url="admin/templates/" controller="Templates" action="List" />
            RoutingAssert.IsRouteOf(_routes, "admin/templates/", new
            {
                controller = "Templates",
                action = "List"
            });
            //<add url="admin/messages/flagged" controller="Messages" action="ListFlagged" />
            RoutingAssert.IsRouteOf(_routes, "admin/messages/flagged", new
            {
                controller = "Messages",
                action = "ListFlagged"
            });
            /*
            <add url="admin/users/{page}" controller="Users" action="List">
			    <defaults>
				    <add key="page" value="0" />
			    </defaults>
		    </add>*/
            RoutingAssert.IsRouteOf(_routes, "admin/users/3", new
            {
                controller = "Users",
                action = "List",
                page = 3
            });
            //<add url="admin/users/delete" controller="Users" action="Delete" />
            RoutingAssert.IsRouteOf(_routes, "admin/users/delete", new
            {
                controller = "Users",
                action = "Delete"
            });
            //<add url="admin/users/promote" controller="Users" action="Promote" />
            RoutingAssert.IsRouteOf(_routes, "admin/users/promote", new
            {
                controller = "Users",
                action = "Promote",
            });
            //<add url="admin/users/demote" controller="Users" action="Demote" />
            RoutingAssert.IsRouteOf(_routes, "admin/users/demote", new
            {
                controller = "Users",
                action = "Demote",
            });
            //<add url="admin/forums/" controller="Forums" action="Manage" />
            RoutingAssert.IsRouteOf(_routes, "admin/forums/", new
            {
                controller = "Forums",
                action = "Manage",
            });
            //<add url="admin/forums/add" controller="Forums" action="Add" />
            RoutingAssert.IsRouteOf(_routes, "admin/forums/add", new
            {
                controller = "Forums",
                action = "Add",
            });
            //<add url="admin/forums/edit" controller="Forums" action="Edit" />
            RoutingAssert.IsRouteOf(_routes, "admin/forums/edit", new
            {
                controller = "Forums",
                action = "Edit",
            });
            //<add url="admin/forums/delete" controller="Forums" action="Delete" />
            RoutingAssert.IsRouteOf(_routes, "admin/forums/delete", new
            {
                controller = "Forums",
                action = "Delete",
            });
            //<add url="admin/unanswered-threads" controller="Forums" action="ListAllUnansweredTopics" />
            RoutingAssert.IsRouteOf(_routes, "admin/unanswered-threads", new
            {
                controller = "Forums",
                action = "ListAllUnansweredTopics",
            });
            //<add url="admin/pages/" controller="PageContents" action="List" />
            RoutingAssert.IsRouteOf(_routes, "admin/pages/", new
            {
                controller = "PageContents",
                action = "List",
            });
            //<add url="admin/pages/add" controller="PageContents" action="Add" />
            RoutingAssert.IsRouteOf(_routes, "admin/pages/add", new
            {
                controller = "PageContents",
                action = "Add",
            });
        }

        [Test]
        public void MessageRouting()
        {
            RoutingAssert.IsRouteOf(_routes, "forums/forumName/topicShortName-10/edit-message/15", new
            {
                controller = "Messages",
                action = "Edit",
                forum = "forumName",
                name = "topicShortName",
                id = 10,
                msgId = 15
            });

            //RouteData rd = _routes.GetRouteData(createHttpConext("/forums/forumName/topicShortName-10/"));
            RequestContext ctx = new RequestContext(createHttpConext("/forums/forumName/topicShortName-10/"), new RouteData());
            string result = UrlHelper.GenerateUrl(null, "Edit", "Messages",
                new RouteValueDictionary(new
                {
                    forum = "forumName",
                    name = "topicShortName",
                    id = 10,
                    msgId = 15
                }), 
                _routes, ctx, true);
            Assert.AreEqual("/forums/forumName/topicShortName-10/edit-message/15", result);

            //string t1 = new UrlHelper(ctx, _routes).Action("Edit", "Messages", new { msgId = 15 });
        }

        private HttpContextBase createHttpConext(string targetUrl = null, string httpMethod="GET")
        {
            // create the mock request
            Mock<HttpRequestBase> mockRequest = new Mock<HttpRequestBase>();
            mockRequest.Setup(m => m.AppRelativeCurrentExecutionFilePath)
                .Returns(targetUrl);
            mockRequest.Setup(m => m.HttpMethod)
                .Returns(httpMethod);
            // create the mock response
            Mock<HttpResponseBase> mockResponse = new Mock<HttpResponseBase>();
            mockResponse.Setup(m => m.ApplyAppPathModifier(It.IsAny<string>()))
                .Returns<string>(s => s);
            // create the mock context, using the request and response
            Mock<HttpContextBase> mockContext = new Mock<HttpContextBase>();
            mockContext.Setup(m => m.Request)
                .Returns(mockRequest.Object);
            mockContext.Setup(m => m.Response)
                .Returns(mockResponse.Object);
            
            // return the mocked context
            return mockContext.Object;
        }
	}
}
